package Code.Objects.Effects.Lasers;

import org.jrabbit.base.graphics.image.Image;
import org.jrabbit.base.graphics.transforms.Color;
import org.jrabbit.base.graphics.transforms.Vector2d;
import org.jrabbit.base.graphics.transforms.listeners.ColorListener;
import org.jrabbit.standard.game.graphics.skins.animation.AnimatedSkin;
import org.jrabbit.standard.game.graphics.skins.image.ImageSkin;
import org.jrabbit.standard.game.objects.particles.ParticleSprite;
import org.jrabbit.standard.game.objects.particles.controllers.generic.ExplosionParticle;
import org.lwjgl.opengl.GL11;

import Code.Basic.Entity.GenericEffect;
import Code.Basic.Entity.PhysicsSprite;

public class Laser extends GenericEffect implements ColorListener
{
	protected float length;
	protected float startPoint;
	protected float skinWidth;
	
	protected LaserTip tip;

	public Laser(String filepath)
	{
		super(filepath);
		setupLaser();
	}

	public Laser(AnimatedSkin skin)
	{
		super(skin);
		setupLaser();
	}

	public void changed(Color color)
	{
		tip.color().set(color);
	}
	
	public void setupLaser()
	{
		tip = new LaserTip();
	}

	public void declareLaser(double x1, double y1, double angle, float offset, float distance)
	{
		location.set(x1, y1);
		rotation.set(angle);
		
		if(distance < offset)
		{
			distance = offset;
		}
		
		length = distance - offset;
		
		double theta = rotation.theta();
		location.addPolar(offset + (length / 2), theta);
		tip.location().set(location);
		tip.location().addPolar(length, theta);
	}
	
	public void declareLaser(double x1, double y1, double x2, double y2, float offset)
	{
		double yDiff = y2 - y1;
		double xDiff = x2 - x1;
		double theta = Math.atan2(yDiff, xDiff);
		float distance = (float) Math.sqrt((xDiff * xDiff) + (yDiff * yDiff));

		location.set(x1, y1);
		rotation.set(Math.toDegrees(theta));

		length = distance - offset;
		double shiftDist = offset + (length / 2);
		location.addPolar(shiftDist, theta);
		tip.location().set(x2, y2);
	}
	
	public void advanceSkinStart(float amount)
	{
		startPoint += amount;
	}
	
	public double getScaledWidth()
	{
		return length;
	}
	
	public void draw()
	{
		if(visible && color.alpha() > 0 && length > 0)
		{
			scalar.flipVertically();
			
				Image image = ((ImageSkin) animation.getSkin()).object();
				image.bind();
				color.bind();
				
				skinWidth = image.getWidth();
				
				GL11.glBegin(GL11.GL_QUADS);
	
					float skinHeight = image.getHeightRatio();
					float textStart = startPoint / skinWidth;
					float numRepetitions = length / skinWidth;
					float width = (float) (length / 2);
					float height = (float) (image.getHeight()/2);
					
					GL11.glTexCoord2f(textStart, 0);
					GL11.glVertex2f(-width, -height);
					
					GL11.glTexCoord2f(textStart + numRepetitions, 0);
					GL11.glVertex2f(width, -height);
					
					GL11.glTexCoord2f(textStart + numRepetitions, skinHeight);
					GL11.glVertex2f(width, height);
					
					GL11.glTexCoord2f(textStart, skinHeight);
					GL11.glVertex2f(-width, height);
				
				GL11.glEnd();
		}
		tip.render();
	}
	
	public void collideWithStructure(PhysicsSprite p)
	{
		//getGameWorld().removeEffect(this);
	}
	
	public void updateGeometry()
	{
		shape.updateShape(location.x(), location.y(), rotation.angle(), length 
				* scalar.getTransformX() / getWidth(), scalar.getTransformY());
	}
	
	public void update(int delta)
	{
		super.update(delta);
		advanceSkinStart(0.05f * delta);
		tip.fizz(delta);
		tip.update(delta);
	}
	
	protected class LaserTip extends ParticleSprite.Images
	{
		private double timer;
		private double sparkInterval = 0.005;
		
		public LaserTip()
		{
			super("Resources/Images/Effects/Lasers/Particle.png");
		}
		
		public void fizz(double time)
		{
			timer += time;
			while(timer > sparkInterval)
			{
				timer -= sparkInterval;
				addParticle(new Spark(this));
			}
		}
		
		public void burst(Vector2d loc)
		{
			addParticle(new Spark(this, loc));
			addParticle(new Spark(this, loc));
		}
		
		private class Spark extends ExplosionParticle
		{
			private Spark(ParticleSprite pS)
			{
				super(pS, 10, 1, 550, 3, 15, 0.5);
			}
			
			private Spark(ParticleSprite pS, Vector2d loc)
			{
				super(pS, 10, 1, 550, 3, 15, 0.5);
				location.set(loc);
			}
		}
	}
}